每個 Vue 的應用都是通過 new Vue() 來建立 Vue Instance
下面建立了一個名為 vm 的 Vue Instance,「vm」為 view model 的簡稱。
var vm = new Vue({
// options
})
view model 來自設計模式 MVVM - model、view 和 view model。
在實體化時,可傳入一個選項物件,結構會像是這樣:
{
el: '#id', // CSS selector 或 HTMLElement 實例
props: {}, // Array<string> 或 Object
data: {}, // Object 或 Function
computed: {}, // { [key: string]: Function | { get: Function, set: Function } }
methods: {}, // { [key: string]: Function }
watch: {}, // { [key: string]: string | Function | Object }
mounted() {} // Function
// ...
}
每個 Vue Instance 在建立時都會經歷一系列初始化步驟,例如,需要設置數據觀察,編譯模板,將實例掛載到 DOM,以及在數據更改時更新 DOM。在初始化過程中,它還運行稱為生命週期鉤子 (Instance Lifecycle Hooks) 的函數,讓開發者可在特定階段添加自己的代碼。
例如:created
鉤子可以用來在創建實例之後運行代碼:
附上 fiddle (https://jsfiddle.net/hunterliu/8fw120n2/)
new Vue({
data: {
a: 1
},
created: function () {
// `this` points to the vm instance
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
另外還有其他鉤子將在實例生命週期的不同階段被調用,比如:
注意:鉤子中的 this 指向調用它的 Vue Instance。
下圖說明了 Vue Instance 的生命週期。
伴隨著對 Vue 的了解,整體的概念也會更清晰。
在看範例之前先附上官方 Lifecycle Diagram,方便對照。
可以從 Lifecycle Diagram 看到這些鉤子有:
在 Vue Instance 初始化之後,但在 data observer 和 event/watcher 被設置之前被執行。
不精確白話文為:此刻你無法調用 data 及 methods。
Vue Instance 已初始化完成,已設置 data, computed, methods, watch/event callbacks,但尚未開始
mounting
階段,且 $el 目前也未掛載。
不精確白話文為:此刻已經可以調用 data, computed, methods, watch等數據或函式。
在
mounting
階段開始前被調用:render function
首次被調用。
選項物件中的
el
被新創建的vm.$el
替換,並掛載到到 vm 上,並調用mounted
這個鉤子。
數據被更新時會調用,發生在 Virtual DOM re-render 和 patch 之前(連結:Day4: Virtual DOM),可以在此時更改狀態數據,並不會增加重新渲染的成本。
由於數據更新導致 Virtual DOM re-render 和 patch 之後會調用
updated
這個鉤子。
不精確白話文為:由於updated
被調用時,DOM 已經更新。所以在此時更新數據很可能會導致updated
無限循環的被調用。
在 Vue Instance 被銷毀前被調用,因此 Vue Instance 在
beforeDestroy
中仍可運作。
不精確白話文為:Vue Instance 可以在此時做垂死前的掙扎。
在 Vue Instance 被銷毀後被調用,此時 Vue Instance 所有東西會解除綁定,事件監聽也都會被移除,子實例也會被銷毀。
用一個範例逐步看到所有的鉤子被調用,並在這個過程中理解被執行的原因。
首先定義一個 Vue Instance 為 vm,而 data 中 msg 的值為Hello Vus.js
,並且當每個鉤子被執行時,簡單的用console.log
記錄該鉤子被執行。
var vm = new Vue({
data: {
msg: 'Hello Vus.js'
},
beforeCreate() {
console.log('beforeCreate 被執行');
},
created() {
console.log('created 被執行');
},
beforeMount() {
console.log('beforeMount 被執行');
},
mounted() {
console.log('mounted 被執行');
},
beforeUpdate() {
console.log('beforeUpdate 被執行');
},
updated() {
console.log('updated 被執行');
},
beforeDestroy() {
console.log('beforeDestroy 被執行');
},
destroyed() {
console.log('destroyed 被執行');
}
});
注意:此時 Vue Instance 中的選項物件暫時還沒有指定el: '#app'
,也請觀察以下四個步驟 HTML 的變化。
看範例時請打開 console。
若此時我們直接運行以上代碼,會發現只有beforeCreate
和created
被執行,因為在整個 Vue Instance 的生命週期執行到created
之後,會先判斷是否有el
這個選項,因為這邊並沒有定義el
,因此需要等到 vm.$mount(el)
被呼叫時,整個生命周期才會繼續進行。
此時的 HTML 顯示 {{msg}}
。
附上 fiddle beforeCreate & created
若添加以下代碼:
vm.$mount('#app');
beforeMount
和mounted
會被執行,而在範例中額外添加了setTimeout
為的是明顯區隔Create
和Mount
分開被執行。
此時的 HTML 顯示 Hello Vus.js
。
附上 fiddle beforeMount & mounted
當 vm 中的 data 有異動時,例如修改 msg
的值:
vm.$data.msg = 'change msg';
beforeUpdate
和updated
會被執行。
此時的 HTML 顯示 change msg
。
附上 fiddle beforeUpdate & updated
可以透過 vm.$destroy()
銷毀 Vue Instance。
vm.$destroy();
beforeDestroy
和destroyed
會被執行。
此時的 HTML 顯示 change msg
。
附上 fiddle beforeUpdate & updated
完整測試範例不只是把所有的鉤子執行一遍,也觀察了數據和DOM的變化。
看範例時請打開 console。
感謝分享
補充 new Vue() 是 Vue 2 的語法,
Vue 3 用 Vue.createApp() 取代 new Vue()
https://book.vue.tw/appendix/migration.html#%E5%85%83%E4%BB%B6%E5%AF%A6%E9%AB%94%E5%BB%BA%E7%AB%8B
Vue 2 support will end on Dec 31, 2023. Learn more about Vue 2 Extended LTS.
The Benefits of the New Vue 3 App Initialization Code